package config

import (
	"errors"
	"fmt"
	"go-caipu/pkg/install/dto"
	"gopkg.in/yaml.v3"
	"os"
	"strings"
)

var ConfigFile = ""

// InitConfig 初使化配置文件
func InitConfig(path string) error {
	//if _, err := os.Stat(path); err != nil {
	//	return fmt.Errorf("读取配置文件失败: %w", err)
	//}
	//viper.SetConfigFile(path)
	////读取配置文件
	//if err := viper.ReadInConfig(); err != nil {
	//	return fmt.Errorf("读取配置文件失败: %w", err)
	//}
	ConfigFile = path
	return nil
}

// 更新YAML配置文件中指定路径的配置项（支持多级路径，如"application.mode"）
// 保留原始注释、缩进和格式
func updateYamlConfig(mp map[string]interface{}) error {
	// 1. 读取原始配置文件
	data, err := os.ReadFile(ConfigFile)
	if err != nil {
		return err
	}

	// 2. 解析为yaml.Node（保留注释和结构）
	var root yaml.Node
	if err := yaml.Unmarshal(data, &root); err != nil {
		return err
	}
	//3 批量更新值
	for key, value := range mp {
		// 3. 按路径查找并更新配置项
		if err := setConfigByPath(root.Content[0], key, value); err != nil {
			return err
		}
	}
	// 4. 写回文件（保留格式）
	output, err := yaml.Marshal(&root)
	if err != nil {
		return err
	}
	return os.WriteFile(ConfigFile, output, 0644)
}

// 按路径（如"application.mode"）查找并更新配置项
func setConfigByPath(node *yaml.Node, path string, value interface{}) error {
	if node.Kind != yaml.MappingNode {
		return errors.New("根节点不是映射类型")
	}

	keys := strings.Split(path, ".")
	if len(keys) == 0 {
		return errors.New("配置路径为空")
	}

	currentNode := node
	for i, key := range keys {
		found := false
		// 遍历当前节点的子节点（YAML映射节点的Content是[key1, value1, key2, value2...]）
		for j := 0; j < len(currentNode.Content); j += 2 {
			keyNode := currentNode.Content[j]
			// 匹配key（忽略大小写？根据实际配置决定，这里严格匹配）
			if keyNode.Value == key {
				valueNode := currentNode.Content[j+1]

				// 如果是最后一级路径，更新值
				if i == len(keys)-1 {
					// 关键修复：根据原始值的类型设置新值（避免类型不匹配导致更新失败）
					switch valueNode.Kind {
					case yaml.ScalarNode:
						// 标量类型（字符串、数字、布尔等）
						valueStr, ok := value.(string)
						if !ok {
							// 非字符串类型转为字符串（如数字、布尔）
							valueStr = fmt.Sprintf("%v", value)
						}
						valueNode.Value = valueStr
						// 保留原始标签（如引号）
						// 例如原始值是"demo"（带引号），更新后仍保留引号
						if valueNode.Style&yaml.DoubleQuotedStyle != 0 {
							valueNode.Style = yaml.DoubleQuotedStyle
						}
					default:
						// 其他类型（如数组、映射）直接序列化
						if err := valueNode.Encode(value); err != nil {
							return fmt.Errorf("编码新值失败: %w", err)
						}
					}
					found = true
					break
				}

				// 非最后一级，进入下一层级（必须是映射节点才能继续）
				if valueNode.Kind != yaml.MappingNode {
					return fmt.Errorf("路径%s的子节点不是映射类型", strings.Join(keys[:i+1], "."))
				}
				currentNode = valueNode
				found = true
				break
			}
		}

		if !found {
			return fmt.Errorf("未找到配置路径: %s", strings.Join(keys[:i+1], "."))
		}
	}
	return nil
}

// UpdateAndWriteConfig 读取配置文件
// 存在问题：遇到配置项重新排序、注释丢失的问题
func UpdateAndWriteConfig(config dto.InstallConfig) error {

	mp := make(map[string]interface{})
	mp["application.installed"] = true
	mp["application.deploy"] = config.DeploymentType
	mp["database.dbType"] = config.Database.Type
	// 根据数据库类型保存相应配置
	if config.Database.Type == "mysql" {
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local",
			config.Database.Username, config.Database.Password, config.Database.Host, config.Database.Port, config.Database.DbName, config.Database.Charset)
		// MySQL配置
		mp["database.dsn"] = dsn
		mp["database.dbName"] = config.Database.DbName
	} else {
		// SQLite配置
		if config.Database.SQLite.Path == "" {
			config.Database.SQLite.Path = "go_caipu.db" // 默认路径
		}
		mp["database.dsn"] = fmt.Sprintf("file:%s", config.Database.SQLite.Path)
	}
	// 如果没有跳过Redis配置，则保存Redis配置
	if config.DeploymentType != "standalone" {
		mp["redis.server"] = fmt.Sprintf("file:%s", fmt.Sprintf("%s:%s", config.Redis.Host, config.Redis.Port))
		mp["redis.password"] = config.Redis.Password
		mp["redis.db"] = config.Redis.Db
	}
	return updateYamlConfig(mp)
}
